//
// Copyright (c) 2004 BroadVision, Inc. All rights reserved.
//
// This software is copyrighted.  Under the copyright laws, this software
// may not be copied, in whole or in part, without prior written consent
// of BroadVision, Inc. or its assignees.  This software is provided under
// the terms of a license between BroadVision and the recipient, and its
// use is subject to the terms of that license.
//
// This software may be protected by one or more U.S. and International
// patents.  Certain applications of BroadVision One-To-One software are
// covered by U.S. patent 5,710,887.
//
// TRADEMARKS: BroadVision and BroadVision One-To-One are registered
// trademarks of BroadVision, Inc., in the United States and the European
// Community, and are trademarks of BroadVision, Inc., in other
// countries.  The BroadVision logo, is a trademark of BroadVision, Inc.,
// in the United States and other countries. Additionally, IONA and Orbix
// are trademarks of IONA Technologies, Ltd.  RSA, MD5, and RC2 are
// trademarks of RSA Data Security, Inc.
//

package com.broadvision.manage.tools.action;

import java.util.List;
import java.util.ArrayList;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.Globals;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import com.broadvision.portal.services.PortalVisitor;
import com.broadvision.visitor.client.VisitorManager;
import com.broadvision.visitor.client.Visitor;
import com.broadvision.visitor.exceptions.VisitorException;
import com.broadvision.system.accesscontrol.client.AccessManager;
import com.broadvision.system.accesscontrol.exceptions.AccessControlException;
import com.broadvision.web.servlet.SessionVisitor;
import com.broadvision.web.action.LoginAction;
import com.broadvision.web.util.ValuePair;
import com.broadvision.manage.tools.ToolsLog;

/**
 * Base class for all member-only related actions. It which will check 
 * whether the visitor has logged in or not. If the visitor has not 
 * logged in, it will forward to logon page. Otherwise, it will 
 * call subclass' processExecute method.
 */
public abstract class BaseAction extends Action {

  public final long UNINITIALIZED_ID = 0;
  
  /**
   * Calls subclass' implementation to do the real work. 
   *  
   * @param mapping <code>ActionMapping</code> object used to select this instance
   * @param form Optional <code>ActionForm</code> bean for this request (if any)
   * @param request <code>HttpServletRequest</code> object to process
   * @param response <code>HttpServletResponse</code> object to process
   * <p> <p>
   * @return <code>ActionForward</code> instance describing where and how
   * control should be forwarded, or null if the response has already been completed
   * <p> <p>
   * @throws Exception if an error occurs
  */
  public ActionForward execute(ActionMapping mapping,
                               ActionForm form,  
                               HttpServletRequest request,
                               HttpServletResponse response)
                        throws Exception {
    SessionVisitor sessionVisitor =
      SessionVisitor.getInstance(request.getSession());
    Visitor visitor = sessionVisitor.getVisitor();

    if (!hasLogin(visitor)) {
      ToolsLog.debug(getClass(),
                     "Visitor is not registered: forwarding to logon");
      if (isBookmarkable()) {
        setNextPage(mapping, request);
        setNextPageParameters(request);
      }
      return mapping.findForward("logon");
    }

    if (!isAuthorized(visitor)) {
      request.setAttribute(Globals.ERROR_KEY, "mc.common.login.permission");
      this.invalidateSession(request);
      return mapping.findForward("logon");
    }

    return processExecute(mapping, form, request, response);
  }
 
  /**
   *
   */ 
  protected void invalidateSession(HttpServletRequest request) {
    request.setAttribute("page_name", "/home.do");
    request.getSession().setAttribute("bv_user_logged_in", "false");
    request.getSession().invalidate();
    request.getSession(true);
  }

  /**
   *
   */ 
  protected boolean hasLogin(Visitor visitor) {
    boolean isRegistered = false;

    isRegistered = visitor.isRegistered();

    return isRegistered;
  }

  /**
   *
   */
  protected boolean isAuthorized(Visitor visitor) {
    return true;
  }

  /**
   *
   */
  protected boolean isUserInRole(Visitor visitor, String role) {
    AccessManager accessMgr = getAccessManager();
    if (accessMgr == null) return false;

    boolean hasRole = false;
    try {
      hasRole = accessMgr.isUserInRole(visitor, role);
    }
    catch (AccessControlException e) {
      ToolsLog.error(this.getClass(), "isUserInRole",
                     "AccessManager.isUserInRole(" + role + ") failed");
    }
    return hasRole;
  }

  /**
   *
   */
  protected boolean checkVisitor(VisitorManager visitorManager, String userAlias) {
    boolean result = false;
    try {
      Visitor visitor = visitorManager.getVisitor(userAlias);
      result = true;
    }
    catch (Exception ex) {
      result = false;
    }
    return result;
  }
  
  /**
   *
   */
  protected boolean checkVisitor(VisitorManager visitorManager, long userId) {
    boolean result = false;
    try {
      Visitor visitor = visitorManager.getVisitor(userId);
      result = true;
    }
    catch (Exception ex) {
      result = false;
    }
    return result;
  }
  
  /**
   *
   */
  protected AccessManager getAccessManager() {
    AccessManager accessMgr = null;
    try {
      accessMgr = AccessManager.instance();
    }
    catch (AccessControlException e) {
      ToolsLog.error(this.getClass(), "getAccessManager",
                     "AccessManager.instance() failed");
    }
    return accessMgr;
  }

  /**
   *
   */
  protected void setNextPage(ActionMapping mapping,
                             HttpServletRequest request) {
    HttpSession session = request.getSession();
    String path = mapping.getPath();

    session.setAttribute(LoginAction.NEXT_PAGE_KEY, path + ".do");
  }

  /**
   *
   */
  protected void setNextPageParameters(HttpServletRequest request) {
    HttpSession session = request.getSession();
    List params = new ArrayList();
    Enumeration names = request.getParameterNames();
    while (names.hasMoreElements()) {
      String name = (String) names.nextElement();
      String[] values = request.getParameterValues(name);

      for (int valueIndex = 0; valueIndex < values.length; valueIndex++) {
        ValuePair valuePair = new ValuePair(values[valueIndex], name);
        params.add(valuePair);
      }
    }
    session.setAttribute(LoginAction.NEXT_PAGE_PARAMS_KEY, params);
  }
 
  /**
   *
   */
  protected Visitor getVisitor(HttpServletRequest request) throws Exception {
    SessionVisitor sessionVisitor =
      SessionVisitor.getInstance(request.getSession());
    Visitor visitor = sessionVisitor.getVisitor();

    return visitor;
  }

  /**
   *
   */
  protected PortalVisitor getPortalVisitor(HttpServletRequest request) throws Exception {
    SessionVisitor sessionVisitor =
      SessionVisitor.getInstance(request.getSession());
    Visitor visitor = sessionVisitor.getVisitor();
    PortalVisitor portalVisitor = sessionVisitor.getPortalVisitor();

    return portalVisitor;
  }
 
  /**
   *
   */
  protected long getUserId(HttpServletRequest request) throws Exception {
    SessionVisitor sessionVisitor =
      SessionVisitor.getInstance(request.getSession());
    Visitor visitor = sessionVisitor.getVisitor();
    long userId = visitor.getId();

    return userId;
  }

  /**
   *
   */
  protected int getServiceId(HttpServletRequest request) {
    SessionVisitor sessionVisitor =
      SessionVisitor.getInstance(request.getSession());
    int serviceId = sessionVisitor.getServiceId();

    return serviceId;
  }

  /**
   *
   */
  protected boolean isBookmarkable() {
    return false;
  }

  /**
   *
   */
  protected abstract ActionForward processExecute(ActionMapping mapping,
                                                  ActionForm form,
                                                  HttpServletRequest request,
                                                  HttpServletResponse response)
                                           throws Exception;
}

